#ifndef __COMPONENT_HEALTH_H__
#define __COMPONENT_HEALTH_H__

#include "Component.hpp"
#include "Engine/MathUtils.hpp"
#include "GameEnum.h"
#include "entt/entity/entity.hpp"
#include <atomic>
#include <functional>
#include "GameLock.hpp"
#include "GameAction.hpp"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct ComponentCreature;
    struct ComponentPlayer;
    struct ComponentOnFire;

    struct ComponentHealth : public Component
    {
        // 生命值，满血的情况下，该值为1,没血的话，值为0
        float health = 1.0f;
        // 氧气值
        float air;
        // 是否会搁浅
        bool canStrand;
        // 氧气容量
        float airCapacity;
        // 攻击抗性
        float attackResilience;
        // 摔落抗性
        float fallResilience;
        // 火焰抗性
        float fireResilience;
        // 尸体保存时间
        float corpseDuration;
        // 死亡时的时间
        double deathTime;
        // 呼吸方式
        BreathingMode breathingMode;

        float lastHealth;

        float healthChange;

        // 无敌时间
        std::atomic<float> invincibleTime;

        ComponentCreature *componentCreature;
        ComponentPlayer *componentPlayer;
        ComponentOnFire *componentOnFire;

        /**
         * @brief 恢复生命值
         * @param amount 恢复的数量，生命值最多也就1，输多了也没用，输入负数也没用
        */
        void heal(float amount);
        
        /**
         * @brief 伤害实体
         * @param amount 扣血数量
         * @param attackerEntity 哪个实体导致的此次伤害
         * @param realInjure 是否为真实伤害，注意：真实伤害的情况下，创造也会受到对应的伤害，除非有无敌时间
         * @param cause 死亡原因，当实体由于此次伤害死亡后将播放的消息
         * @param injureType 伤害类型，伤害类型为Plugin，无视无敌，并且其它插件将无法捕捉到该伤害事件
        */
        void injure(float amount, entt::entity attackerEntity, bool realInjure, const std::string &cause, InjureType injureType = InjureType::Unknow);

        virtual void update(float dt) override;
        virtual const std::string &getName() const override;
        static const std::string &GetName();
        virtual void load(const nlohmann::json &jsonData) override;
        virtual void save(nlohmann::json &jsonData) override;
        virtual void saveToMsgJson(nlohmann::json &jsonData) override;

        // 只能在load的时候添加行为
        void addAttackedEvent(std::function<void(entt::entity)> event);

    protected:
        void netInjure(float amount, entt::entity attackerEntity, const std::string &cause);

    protected:
        SpinLock m_healthLock;

        GameAction<entt::entity> m_attackedEvents;
    };
    
} // namespace PocketSurvival

#endif